/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jsf;

import com.icesoft.faces.context.ByteArrayResource;
import com.icesoft.faces.context.FileResource;
import com.icesoft.faces.context.Resource;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.DefaultFontMapper;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import entidades.Ensayo;
import entidades.Formulario;
import entidades.Usuario;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import jpa.FormularioJpaController;
import jsf.util.JsfUtil;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;
import java.io.*;

import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpServletResponse;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.util.Log;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

/**
 *
 * @author dvasquez
 */
public class InformeController {

    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
    /** Creates a new instance of InformeController */
    boolean busquedaInforme = false;
    private Usuario usuario = null;
    private java.util.List<Formulario> formularios = null;
    private FormularioJpaController formularioJpa = null;
    private UsuarioConverter converter = null;
    private Date fechaInicio, fechaFinal;
    private static Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 18, Font.BOLD);
    private static Font redFont = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.NORMAL);
    private static Font blueFont = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.NORMAL);
    private static Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.NORMAL);
    private static Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.BOLD);
    private int asfalto = 0, suelos = 0, hormigones = 0;
    private int marshall = 0, dcas = 0, ctemp = 0, ctr = 0, masfalto = 0, hilo = 0, dcd = 0, dcar = 0, tms = 0, tmh = 0;
    private Boolean existeInforme = false, generado = false;
    private byte[] byteArray = null;


    public InformeController() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        converter = new UsuarioConverter();
        formularioJpa = (FormularioJpaController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(), null, "formularioJpa");
        fechaInicio = new Date();
        fechaFinal = new Date();
        redFont.setColor(BaseColor.RED);
        blueFont.setColor(BaseColor.BLUE);
    }

    public boolean isBusquedaInforme() {
        return busquedaInforme;
    }

    public void setBusquedaInforme(boolean busquedaInforme) {
        this.busquedaInforme = busquedaInforme;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    public Date getFechaFinal() {
        return fechaFinal;
    }

    public void setFechaFinal(Date fechaFinal) {
        this.fechaFinal = fechaFinal;
    }

    public Date getFechaInicio() {
        return fechaInicio;
    }

    public void setFechaInicio(Date fechaInicio) {
        this.fechaInicio = fechaInicio;
    }

    public String rangoSetup() {
        generado = false;
        return scalarSetup("informe_create");
    }


    public void setExisteInforme(Boolean existeInforme) {
        this.existeInforme = existeInforme;
    }

    public String generarInforme() throws ParseException {
        String path = "", archivo = "";
        DateTime jodaDT;
        FacesContext fc = null;
        try {
            if (fechaInicio == null || fechaFinal == null) {
                JsfUtil.addErrorMessage("Debe ingresar fecha de inicio y fecha de término.");
                return null;
            }
            if (fechaInicio.after(fechaFinal)) {
                JsfUtil.addErrorMessage("La fecha de inicio debe ser anterior a la fecha de término.");
                return null;
            }
            Random random = new Random();
            int azar = random.nextInt(1000);
            Document doc = new Document();
            fc = FacesContext.getCurrentInstance();
            ServletContext sc = (ServletContext) fc.getExternalContext().getContext();
            //archivo = "resultado" + String.valueOf(azar) + ".pdf";
            archivo = "resultado.pdf";
            path = sc.getRealPath("/") + archivo;
            //ClassLoader loader = Thread.currentThread().getContextClassLoader();
            //String path = loader.getResource("web.xml").toURI().getPath();
            PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(path));
            //com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance("lepucv_logo.jpg");
            doc.open();
            //Rectangle pagesize = new Rectangle(10,10,10,10);
            doc.setMargins(40, 40, 40, 40);
            doc.addTitle("Informe de Laboratorista.");
            doc.addSubject("Informe");
            doc.addKeywords("Lepucv, construccion");
            Paragraph preface = new Paragraph();
            addEmptyLine(preface, 1);
            com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance("web1.png");
            image.setAlignment(Image.ALIGN_CENTER);
            image.scalePercent(50);
            preface.add(image);
            addEmptyLine(preface, 2);
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("RUT: ", blueFont));
            preface.add(new Chunk(usuario.getRut() + "-" + usuario.getDigito(), subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Nombres: ", blueFont));
            preface.add(new Chunk(usuario.getPrimerNombre() + " " + usuario.getSegundoNombre(), subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Apellidos: ", blueFont));
            preface.add(new Chunk(usuario.getApellidoPaterno() + " " + usuario.getApellidoMaterno(), subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Periodo: ", blueFont));
            SimpleDateFormat df;
            df = new SimpleDateFormat("dd-MM-yyyy");
            jodaDT = new DateTime(fechaInicio);

            String fechai = jodaDT.toString("dd-MM-yyyy");

            jodaDT = new DateTime(fechaFinal);

            String fechaf = jodaDT.toString("dd-MM-yyyy");

            preface.add(new Chunk(fechai + " a " + fechaf, subFont));
            doc.add(preface);
            //formularios = usuario.getFormularioCollection();
            formularios = formularioJpa.findFormularioByRangoAndUser(fechaInicio, fechaFinal, usuario.getRut());
            preface = new Paragraph();
            addEmptyLine(preface, 2);
            preface.add(new Chunk("Cantidad de formularios ingresados: ", blueFont));
            preface.add(new Chunk("" + formularios.size(), subFont));
            doc.add(preface);
            preface = new Paragraph();
            addEmptyLine(preface, 2);
            preface.setAlignment(Paragraph.ALIGN_CENTER);
            preface.add(new Chunk("Formularios por área", catFont));
            doc.add(preface);
            /*
            formularios = formularioJpa.findFormularioByRangoUserArea(fechaInicio, fechaInicio, usuario.getRut(), "Asfalto");
            asfalto = formularios.size();
            formularios = formularioJpa.findFormularioByRangoUserArea(fechaInicio, fechaInicio, usuario.getRut(), "Suelos");
            suelos = formularios.size();
            formularios = formularioJpa.findFormularioByRangoUserArea(fechaInicio, fechaInicio, usuario.getRut(), "Hormigones");
            hormigones = formularios.size();*/
            for (Formulario f : formularios) {
                if (f.getCodigoEnsayo().getArea().equals("Asfalto")) {
                    asfalto++;
                }
                if (f.getCodigoEnsayo().getArea().equals("Suelos")) {
                    suelos++;
                }
                if (f.getCodigoEnsayo().getArea().equals("Hormigones")) {
                    hormigones++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("00S")) {
                    tms++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("010")) {
                    tmh++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("019")) {
                    dcd++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("073")) {
                    masfalto++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("031")) {
                    marshall++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("043")) {
                    dcas++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("057")) {
                    ctemp++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("065")) {
                    ctr++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("087")) {
                    hilo++;
                }
                if (f.getCodigoEnsayo().getCodigoEnsayo().equals("092")) {
                    dcar++;
                }
            }
            writeChartToPDF(generateBarChartArea(), 40, 50, 500, 400, writer);
            doc.newPage();
            preface = new Paragraph();
            preface.setAlignment(Paragraph.ALIGN_CENTER);
            preface.add(new Chunk("Formularios por tipo de ensayo", catFont));
            doc.add(preface);
            preface = new Paragraph();
            addEmptyLine(preface, 2);
            preface.add(new Chunk("Marshall de Control: ", blueFont));
            preface.add(new Chunk("" + marshall, subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Densidades Carpeta Asfáltica: ", blueFont));
            preface.add(new Chunk("" + dcas, subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Control Temperatura: ", blueFont));
            preface.add(new Chunk("" + ctemp, subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Control Tasa de Riego: ", blueFont));
            preface.add(new Chunk("" + ctr, subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Muestreo Asfalto: ", blueFont));
            preface.add(new Chunk("" + masfalto, subFont));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Hi-Lo: ", blueFont));
            preface.add(new Chunk("" + hilo));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Densidades con Densímetro: : ", blueFont));
            preface.add(new Chunk("" + dcd));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Densidades con Cono de Arena:  ", blueFont));
            preface.add(new Chunk("" + dcar));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Toma de Muestra de Suelo: ", blueFont));
            preface.add(new Chunk("" + tms));
            doc.add(preface);
            preface = new Paragraph();
            preface.add(new Chunk("Toma de Muestra de Hormigón: ", blueFont));
            preface.add(new Chunk("" + tmh));
            doc.add(preface);
            writeChartToPDF(generatePieChartEnsayo(), 40, 150, 500, 400, writer);
            doc.close();
            byteArray = new byte[5000000];
            InputStream is = new FileInputStream(path);
            int read = 0;
            while(read != -1)
                read = is.read(byteArray);
            is.close();

            asfalto = 0;
            suelos = 0;
            hormigones = 0;
            tms = 0;
            tmh = 0;
            dcd = 0;
            masfalto = 0;
            marshall = 0;
            dcas = 0;
            ctemp = 0;
            ctr = 0;
            hilo = 0;
            dcar = 0;
        } catch (FileNotFoundException ex) {
            Logger.getLogger(InformeController.class.getName()).log(Level.SEVERE, null, ex);
            JsfUtil.addErrorMessage("No se encontró el archivo. Debe crear un informe primero.");
            return "welcome";
        } catch (DocumentException ex) {
            Logger.getLogger(InformeController.class.getName()).log(Level.SEVERE, null, ex);
            JsfUtil.addErrorMessage("Error al generar el informe. Por favor intente denuevo.");
            return "welcome";
        } catch (IOException ex) {
            Logger.getLogger(InformeController.class.getName()).log(Level.SEVERE, null, ex);
            JsfUtil.addErrorMessage("Error al manejar el archivo. Intente regenerar el informe.");
            return "welcome";
        } catch (Exception ex) {
            Logger.getLogger(InformeController.class.getName()).log(Level.SEVERE, null, ex);
            return "welcome";
        }
        JsfUtil.addSuccessMessage("Informe creado exitosamente. Puede visualizar el informe haciendo clic en el botón \"Mostrar PDF\".");
        //try {
           // ExternalContext e = fc.getExternalContext();
            //HttpServletResponse response = (HttpServletResponse)fc.getExternalContext().getResponse();
            //response.sendRedirect(archivo);
            //path = e.getRequestContextPath() + archivo;
            //e.redirect("usuario/Search.iface");
        //} catch (IOException ex) {
           // Logger.getLogger(InformeController.class.getName()).log(Level.SEVERE, null, ex);
        //}
        generado = true;
        return "";

    }

    public Boolean getGenerado() {
        return generado;
    }

    public void setGenerado(Boolean generado) {
        this.generado = generado;
    }

    private static void addEmptyLine(Paragraph paragraph, int number) {
        for (int i = 0; i < number; i++) {
            paragraph.add(new Paragraph(" "));
        }
    }

    private String scalarSetup(String destination) {
        this.busquedaInforme = false;
        usuario = (Usuario) JsfUtil.getObjectFromRequestParameter("jsfcrud.currentUsuario", converter, null);
        if (usuario == null) {
            String requestUsuarioString = JsfUtil.getRequestParameter("jsfcrud.currentUsuario");
            JsfUtil.addErrorMessage("El usuario con RUT " + requestUsuarioString + " ya no existe.");
        }
        return destination;
    }

    public String usuarioSearch() {
        clearUsuario(usuario);
        return "usuario_search";
    }

    public void clearUsuario(Usuario user) {
        if (user != null) {
            user.setRut("");
            user.setDigito(null);
            user.setPrimerNombre("");
            user.setSegundoNombre("");
            user.setApellidoPaterno("");
            user.setApellidoMaterno("");
        }
    }

    public JFreeChart generateBarChartArea() {
        DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
        dataSet.clear();
        dataSet.setValue(suelos, "Formularios", "Suelos");
        dataSet.setValue(asfalto, "Formularios", "Asfalto");
        dataSet.setValue(hormigones, "Formularios", "Hormigón");

        JFreeChart chart = ChartFactory.createBarChart("", "Área", "Cantidad de formularios", dataSet, PlotOrientation.VERTICAL, false, true, false);
        return chart;
    }

    public JFreeChart generateBarChartEnsayo() {
        DefaultCategoryDataset dataSet = new DefaultCategoryDataset();
        dataSet.clear();
        dataSet.setValue(marshall, "Ensayos", "Marshall de Control");
        dataSet.setValue(dcas, "Ensayos", "Densidades Carpeta Asfáltica");
        dataSet.setValue(ctemp, "Ensayos", "Control Temperatura");
        dataSet.setValue(ctr, "Ensayos", "Control Tasa de Riego");
        dataSet.setValue(masfalto, "Ensayos", "Muestreo Asfalto");
        dataSet.setValue(hilo, "Ensayos", "Hi-Lo");
        dataSet.setValue(dcd, "Ensayos", "Densidades con Densímetro");
        dataSet.setValue(dcar, "Ensayos", "Densidades con Cono de Arena");
        dataSet.setValue(tms, "Ensayos", "Toma de Muestra de Suelo");
        dataSet.setValue(tmh, "Ensayos", "Toma de Muestra de Hormigón");
        JFreeChart chart = ChartFactory.createBarChart("", "Ensayo", "Cantidad de formularios", dataSet, PlotOrientation.VERTICAL, false, true, false);
        

        return chart;
    }

    public JFreeChart generatePieChartEnsayo() {
        DefaultPieDataset dataSet = new DefaultPieDataset();
        dataSet.clear();
        dataSet.setValue("Marshall de Control", marshall);
        dataSet.setValue("Densidades Carpeta Asfáltica", dcas);
        dataSet.setValue("Control Temperatura", ctemp);
        dataSet.setValue("Control Tasa de Riego", ctr);
        dataSet.setValue("Muestreo Asfalto", masfalto);
        dataSet.setValue("Hi-Lo", hilo);
        dataSet.setValue("Densidades con Densímetro", dcd);
        dataSet.setValue("Densidades con Cono de Arena", dcar);
        dataSet.setValue("Toma de Muestra de Suelo", tms);
        dataSet.setValue("Toma de Muestra de Hormigón", tmh);
        JFreeChart chart = ChartFactory.createPieChart("", dataSet, true, true, false);

        return chart;
    }

    public static void writeChartToPDF(JFreeChart chart, int startx, int starty, int width, int height, PdfWriter writer) {

        try {
            PdfContentByte contentByte = writer.getDirectContent();
            PdfTemplate template = contentByte.createTemplate(width, height);
            Graphics2D graphics2d = template.createGraphics(width, height, new DefaultFontMapper());
            Rectangle2D rectangle2d = new Rectangle2D.Double(0, 0, width, height);
            chart.draw(graphics2d, rectangle2d);

            graphics2d.dispose();
            contentByte.addTemplate(template, startx, starty);
            

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public Resource getRecurso(){
        if(byteArray == null)
            return null;
        else
            return new ByteArrayResource(byteArray);
    }

    public void validateFecha(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        DateTime fecha = new DateTime(value);
        boolean b = Pattern.matches("(0[1-9]|[1-9]|[12][0-9]|3[01])-(0[1-9]|1[012]|[1-9])-(19|20)\\d{2}", fecha.toString("dd-MM-aaaa"));
        if (!b) {
            FacesMessage fm = new FacesMessage(FacesMessage.SEVERITY_ERROR, "La fecha ingresada no es válida. debe tener el formato dd-mm-aaaa.", null);
            context.addMessage(null, fm);
            throw new ValidatorException(fm);
        }
    }

}
